// 封装请求模块

import axios from 'axios'

import { Toast } from 'vant'

// json-bigint 会把超出 JS 安全整数范围的数字转为一个 BigNumber 类型的对象，
// 对象数据是它内部的一个算法处理之后的，我们要做的就是在使用的时候转为字符串来使用。
import jsonBig from 'json-bigint'

// 在非组件模块中获取 store 必须通过这种方式
// 这里单独加载 store，和在组件中 this.$store 一个东西
import store from '@/store/'
import router from '@/router/'

// 创建新的 axios 实例
const refreshTokenReq = axios.create({
    baseURL: 'http://ttapi.research.itcast.cn/'
})

const request = axios.create({
    baseURL: 'http://ttapi.research.itcast.cn/',

    // transformResponse 允许自定义原始的响应数据（字符串）
    transformResponse: [function (data) {
        try {
            // 如果转换成功则返回转换的数据结果
            return jsonBig.parse(data)
        } catch (err) {
            // 如果转换失败，则包装为统一数据格式并返回
            return {
                data
            }
        }
    }]
})

// 请求拦截器
// Add a request interceptor
request.interceptors.request.use(function (config) {
    // Do something before request is sent
    const { user } = store.state
    // 如果用户已登录，就给接口统一添加 token
    if (user) {
        config.headers.Authorization = `Bearer ${user.token}`
    }
    return config
}, function (error) {
    // Do something with request error
    return Promise.reject(error)
})

// 响应拦截器
// 使用响应拦截器统一处理请求失败的情况
// Add a response interceptor
request.interceptors.response.use(function (response) {
    // Any status code that lie within the range of 2xx cause this function to trigger
    // Do something with response data
    return response
}, async function (error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error

    const status = error.response.status

    if (status === 400) {
        // 客户端请求参数错误
        Toast.fail('客户端请求参数错误!')
    } else if (status === 401) {
        // token 无效
        const { user } = store.state
        // 判断 有没有 user
        if (!user || !user.token) {
            // 跳转到登录页
            return redirectLogin()
        }

        // 使用 refresh_token 请求获取新的 token
        try {
            const { data: res } = await refreshTokenReq({
                method: 'PUT',
                url: '/app/v1_0/authorizations',
                headers: {
                    Authorization: `Bearer ${user.refresh_token}`
                }
            })
            // console.log(res)
            // 拿到新的 token 更新到容器中
            user.token = res.data.token
            store.commit('setUser', user)

            // 把失败的请求重新发送
            // error.config 是本次请求的相关配置信息对象
            return request(error.config)
        } catch (error) {
            redirectLogin()
        }
    } else if (status === 403) {
        // 没有权限
        Toast.fail('没有权限!')
    } else if (status >= 500) {
        // 服务端异常
        Toast.fail('服务端异常!')
    }

    return Promise.reject(error)
})

function redirectLogin () {
    router.replace({
        name: 'login',
        query: {
            // 数据名是自己起的
            // router.currentRoute 和我们在组件中获取的 this.$route 是一个东西
            redirect: router.currentRoute.fullPath
        }
    })
}

// 导出
export default request
